摄像头(以 OV5647 为例)
本节以 OV5647 摄像头模组为例,说明在 NG4520 平台的开发适配流程,涵盖硬件前置、设备树、驱动编译、系统加载和调试等完整步骤。
Camera 架构与名词解释
名词 | 解释 |
---|---|
ISP | 图像信号处理器,用于图像去噪、白平衡、色彩校正等。 |
Bayer | 即摄像头传感器,使用Bayer滤色阵列捕获图像。 |
CSI | 摄像头串行接口,用于摄像头与处理器之间的数据传输。 |
V4L2 | Linux内核的视频捕获和输出框架。 |
libargus | NVIDIA提供的高级摄像头控制库。 |
Camera Core Library | 提供应用程序与内核模式V4L2驱动程序之间的控制和处理功能。 |
GStreamer | 开源的多媒体处理框架,用于音视频处理。 |
Host1x | NVIDIA Tegra SoC中的主机接口控制器。 |
Aperture | 光圈控制,用于调节镜头的光圈大小。 |
UVC | USB视频类,用于USB摄像头的驱动程序。 |
VI | 视频输入模块,用于接收和处理视频数据。 |
Camera 软件架构说明
NVIDIA 平台支持两种 Camera 驱动架构:
- Camera Core Library Interface:支持 ISP 访问和高级图像处理,应用层通过 libargus API 访问(如
nvgstcapture-1.0
工具)。 - Direct V4L2 Interface:直接使用 V4L2 驱动,不支持 NVIDIA ISP。
建议开发时采用 Camera Core Library Interface,以便充分利用 NVIDIA ISP 能力。
OV5647 驱动适配流程
前置条件
-
获取摄像头 I2C 地址及线序,确认 PWDN/RESET 引脚
-
获取上电时序、外部时钟、支持分辨率/帧率、滤色器阵列类型(BGGR/GBRG/GRBG/RGGB)
-
确认连接接口及 tegra_sinterface 对应关系(如 NG452X 平台 cam0=serial_c)
本例基于 Jetson Orin NX,硬件连接接口为 cam0。**
设备树配置
-
创建设备树 Overlay 文件,路径示例如下:
Linux_for_Tegra/source/hardware/nvidia/t23x/nv-public/overlay/tegra234-p3767-camera-p3768-ov5647.dts`
-
tegra-camera-platform 节点配置,配置视频流端口及连接关系,示例:
tegra-capture-vi {
num-channels = <1>;
ports {
#address-cells = <1>;
#size-cells = <0>;
vi_port1: port@1 {
reg = <0>;
rbpcv2_ov5647_vi_in1: endpoint {
port-index = <2>;
bus-width = <2>;
remote-endpoint = <&rbpcv2_ov5647_csi_out1>;
};
};
};
}; -
I2C 设备节点配置
配置摄像头参数(I2C 地址、模式、时钟、分辨率等):
rbpcv2_ov5647_c@36 {
reset-gpios = <&gpio CAM0_RST GPIO_ACTIVE_HIGH>;
pwdn-gpios = <&gpio CAM1_PWDN GPIO_ACTIVE_HIGH>;
compatible = "ovti,ov5647";
/* I2C device address */
reg = <0x36>;
/* V4L2 device node loation */
devnode = "video0";
/* Physical dimensions of sensor */
physical_w = "3.670";
physical_h = "2.740";
sensor_model = "ov5647";
use_sensor_mode_id = "true";
clocks = <&bpmp TEGRA234_CLK_EXTPERIPH2>,
<&bpmp TEGRA234_CLK_PLLP_OUT0>;
clock-names = "extperiph2", "pllp_grtba";
mclk = "extperiph2";
clock-frequency = <24000000>;
mode0 { /* ov5647_MODE0_1920x1080_30FPS */
mclk_khz = "25000";
num_lanes = "2";
// lane_polarity = "4";
tegra_sinterface = "serial_c";
phy_mode = "DPHY";
discontinuous_clk = "yes";
dpcm_enable = "false";
cil_settletime = "0";
active_w = "1920";
active_h = "1080";
mode_type = "bayer";
pixel_phase = "bggr";
csi_pixel_bit_depth = "10";
readout_orientation = "90";
line_length = "2416";
inherent_gain = "1";
mclk_multiplier = "3.6669";
pix_clk_hz = "81666663";
gain_factor = "16";
framerate_factor = "1000000";
exposure_factor = "1000000";
min_gain_val = "16";
max_gain_val = "128";
step_gain_val = "1";
default_gain = "16";
min_hdr_ratio = "1";
max_hdr_ratio = "1";
min_framerate = "30000000"; /* 30.0 fps */
max_framerate = "30000000"; /* 30.0 fps */
step_framerate = "1";
default_framerate = "45000000"; /* 30.0 fps */
min_exp_time = "60"; /* us */
max_exp_time = "30000"; /* us */
step_exp_time = "1";
default_exp_time = "10000"; /* us */
embedded_metadata_height = "0";
};
........................
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
rbpcv2_ov5647_out1: endpoint {
status = "okay";
port-index = <1>;
bus-width = <2>;
remote-endpoint = <&rbpcv2_ov5647_csi_in1>;
};
};
};
}; -
端口绑定配置
-
通过
remote-endpoint
连接摄像头、CSI 和 VI 模块,确保视频流通路完整。tegra-capture-vi {
num-channels = <1>;
ports {
#address-cells = <1>;
#size-cells = <0>;
vi_port1: port@1 {
reg = <0>;
rbpcv2_ov5647_vi_in1: endpoint {
port-index = <2>;
bus-width = <2>;
remote-endpoint = <&rbpcv2_ov5647_csi_out1>;
};
};
};
};
host1x@13e00000 {
nvcsi@15a00000 {
num-channels = <1>;
#address-cells = <1>;
#size-cells = <0>;
csi_chan1: channel@1 {
reg = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
csi_chan1_port0: port@0 {
reg = <0>;
rbpcv2_ov5647_csi_in1: endpoint@2 {
port-index = <2>;
bus-width = <2>;
remote-endpoint = <&rbpcv2_ov5647_out1>;
};
};
csi_chan1_port1: port@1 {
reg = <1>;
rbpcv2_ov5647_csi_out1: endpoint@3 {
remote-endpoint = <&rbpcv2_ov5647_vi_in1>;
};
};
};
};
};
};
-
-
Overlay Makefile 配置,在
overlay/Makefile
添加:dtbo-y += tegra234-p3767-camera-p3768-ov5647.dtbo
-
编译生成 dtbo:
make dtbs
驱动开发与编译
-
添加驱动源码**
- 路径示例:
drivers/media/i2c/ov5647.c
- 推荐基于
nv_ov5693.c
修改。 - 主要实现:
tegracam_device_register
注册驱动- 填充以下结构体:
tc_dev->sensor_ops
(上电、下电、读写寄存器、模式设置、流控制等)tc_dev->v4l2sd_internal_ops
(如 open/s_stream)tc_dev->tcctrl_ops
(增益、曝光、帧率控制等)
static struct tegracam_sensor_ops ov5647_sensor_ops = {
.power_on = ov5647_power_on,
.power_off = ov5647_power_off,
.write_reg = ov5647_write_reg,
.read_reg = ov5647_read_reg,
.set_mode = ov5647_set_mode,
.start_streaming = ov5647_start_streaming,
.stop_streaming = ov5647_stop_streaming,
.sensor_init = ov5647_sensor_init,
};这些函数的具体实现需要根据 OV5647 的数据手册和相关文档进行编写。
-
添加寄存器表头文件
- 路径示例:
drivers/media/i2c/ov5647_modes_tbls.h
- 包含各分辨率、曝光等寄存器配置表,需与设备树 mode 顺序保持一致。
static struct v4l2_subdev_internal_ops ov5647_subdev_internal_ops = {
.open = ov5647_open,
}; - 路径示例:
- 路径示例:
-
驱动 Makefile 配置,在
drivers/media/i2c/Makefile
添加:obj-m += ov5647.o
-
编译生成内核模块:
make modules